/* $Id: all.js 7 2011-09-22 19:46:27Z adriftrock@gmail.com $ */


/**
 * Request information from server
 */
var Request = function () {
    this.urlPrefix = "http://localhost:8080/";
    this.urlByOrg = "http://localhost:8080/@target/byorg?id=@id&callback=?";
};
Request.prototype = {

    url: function(target, id) {
       if (!id) id = orgs.root.id;
       return req.urlByOrg.replace("@target", target).replace("@id", id);
    },

    load: function(target) {
        this.handle(target)
    },

    handle: function(t) {
        $("#content").load("/" + t, function(resp, status, xhr) {
            if (status == "error") {
                var msg = "Sorry but there was an error: ";
                tool.showHint("<h5 style='color:#900;'>" + msg + xhr.status + " " + xhr.statusText + "</h5>");
            }
            if (status == "success") {
                req.getJsonp(t, true);
                $(".v-menuitem").click(function() { menu.click(this.id); } );
                $(".v-menuitem").hover(function() {
                    $(this).addClass("boxtitleover"); }, function() {
                    $(this).removeClass("boxtitleover");
                });
            }
        });
    },

    getJsonp: function(t, visible) {
        switch(t) {
            case "organization":
                if (orgs.saved.length == 0) {
                    if (visible) orgn.load(orgn.list);
                    else orgn.load();
                } else {
                    orgn.list();
                }

            break;
            case "position":
                if (post.saved.length == 0) {
                    if (visible) posi.load(posi.list);
                    else posi.load();
                } else {
                    posi.list();
                }
            break;
            case "personnel":
                if (emps.saved.length == 0) {
                    if (visible) empl.load(empl.list);
                    else empl.load();
                } else {
                    empl.list();
                };
            break;
            case "dashboard":
                dashboard.loadOverview();
                dashboard.loadDepts();
                dashboard.loadPosts();
                dashboard.loadPeople();
            break;
            default:
        }

    }
};

//==============================================================================

/**
 * Organization operations.
 */
var Org = function() {
    // use 'orgs' as a cache to put Organization Flag
    window.orgs = { saved:[], temp:{ created:{}, updated:{}, removed:[] } };
};
Org.prototype = {
    save: function() {
        alert(JSON.stringify(orgs.temp));
        var carrier = [];
        for (var c in orgs.temp.created) carrier.push(orgs.temp.created[c]);
        for (var u in orgs.temp.updated) carrier.push(orgs.temp.updated[u]);
        if (orgs.temp.removed.length > 0) carrier.push({id:-1, comment:JSON.stringify(orgs.temp.removed)});
        var s = JSON.stringify(carrier);
        alert(s);
        $.post("/organization", {"carrier":s}, function(data) {
            alert(JSON.stringify(data));
            orgs.temp.created = {};
            orgs.temp.updated = {};
            orgs.temp.removed = [];
            orgs.saved = [];
            carrier = null;
            req.load("organization");
        });
    },
    remove: function() {
        var flag = $(".checkedFlag");
         if (flag.length == 0) {
             tool.showHint("Please select an Organization Flag that wants to remove.");
             return false;
         }

        var o = $(".checkedFlag");
        o.addClass("rmFlag");

        var i = o.index();
        if ($(".checkedFlag li[title='id']").text()) {
            var id = orgs.saved[i].id;
            id = parseInt(id);
            var dialog = new Dialog("#orgForm");
            if ($.inArray(id, orgs.temp.removed) == -1) {
                orgs.temp.removed.push(id);
            }
            dialog.change = true;
            dialog.remindSave();
        }
    },
    update: function() {
        var flag = $(".checkedFlag");
         if (flag.length == 0) {
             tool.showHint("Please select an Organization that wants to update.");
             return false;
         }
        var i = flag.index();
        var oCached = orgs.temp.created[i];
        var isNew = false;
        var checkedId = $(".checkedFlag li[title='id']").text();
        if (checkedId) { // is saved or not
            this.setInput(orgs.saved[i]);
            oCached = orgs.saved[i];
        } else {
            this.setInput(orgs.temp.created[i]);
            isNew = true;
        }

        var dialog = new Dialog("#orgForm");
        dialog.setButton(1, "Update");
        dialog.show();
        dialog.btn1Click = function() {
            if (!this.validate()) return false;

            var isUpdated = false;
            var n = $("input#name").val().trim();
            if (n != oCached.name) { oCached.name = n; isUpdated = true; }
            var t = $(":radio:checked").val();
            if (t != oCached.orgType) { oCached.orgType = t; isUpdated = true; }
            // todo: allowed to update parentId

            if (isUpdated && !isNew) {
                orgs.temp.updated[i] = oCached;
                this.change = true;
            }
            if (isUpdated) {
                $(".checkedFlag li[title='name']").html("<b>" + oCached.name + "</b>");
            }
        };
    },
    add: function() {
        var flag = $(".checkedFlag");
         if (flag.length == 0) {
             tool.showHint("Please select an Organization as a root.");
             $(".v-menuitem").removeClass("clicked");
             return false;
         }
        var dialog = new Dialog("#orgForm");
        dialog.setButton(1, "Add and Continue");
        dialog.show();
        dialog.btn1Click = function() {
            if (!this.validate()) return false;

            var k = $(".flag").length;
            orgs.temp.created[k] = {"name":$("input#name").val(),
                "orgType":$(":input:radio:checked").val(),
                "parent": $(".checkedFlag li[title='id']").text()
            };
            this.change = true;
            console.log("New Org: " + JSON.stringify(orgs.temp.created[k]));

            var flag = $("<div class='flag'></div>");
            orgn.showFlag(orgs.temp.created[k], flag);
            tool.reset(this.id);
            console.log("Create a temperary Org Flag: " + JSON.stringify(orgs));
        };
    },
    load: function(fn, uri) {
        orgn.root();
        orgs.saved[0] = orgs.root;
        if (!uri) uri = req.url("organization");
        $.getJSON(uri, function(data) {
            if (data) {
                $.merge(orgs.saved, data.organization);
            }
            if (fn) fn();
        });
    },
    list: function() {
            for (var i = 0; i < orgs.saved.length; i++) {
                var flag = $("<div class='flag'></div>");
                orgn.showFlag(orgs.saved[i], flag);
            }
        //if ($("#orgRoot").text() == "") orgn.showFlag(orgs.root);
    },
    root: function() {
      if (orgs.root) return;
      orgs.root = getCookieObj("email");
        $.getJSON(req.urlPrefix + "organization/" + orgs.root.id + "?callback=?",
        function(data){
            var div = $("#overview");
            div.empty();
            if (data) {
                orgs.overview = data;
            } else {
                orgs.overview = orgs.root;
            }
            dashboard.loadOverview();
        });
    },

    setInput: function(o) {
        $("input#name").val(o.name);
        if (o.orgType) {
            $("input#" + o.orgType).attr("checked","true");
            $("#orgTypeSelector").show();
        }
        else {
            $("#orgTypeSelector").hide();
        }
    },
    showFlag: function(o, flag, isNew) {
        if (o.id == orgs.root.id) {
            flag = $("#orgRoot");
        }
        else {
            $("#orgListDiv").append(flag);
            flag.addClass("column");
        }
        if (o.id) $("<li title='id' style='display:none;'>").append(o.id).appendTo(flag);
        $("<li title='name'>").append("<b>" + o.name + "</b>").appendTo(flag);
        if (o.email) $("<li title='email'>").append(o.email).appendTo(flag);
        if (o.phoneNumber) $("<li title='phoneNumber'>").append(o.phoneNumber).appendTo(flag);

        this.blink(flag);

    },
    blink: function(o) {
        o.hover(function() {
            $(this).addClass("hoverFlag");
        }, function() {
            $(this).removeClass("hoverFlag");
        });
        o.click(function() {
                $(".checkedFlag").removeClass("checkedFlag");
                $(this).addClass("checkedFlag");
                tool.hideHint();
            }
        );
    }
}

//==============================================================================

/**
 * Personnel operations
 */
var Emp = function() {
    window.emps = { saved:[], temp:{ created:{}, updated:{}, removed:[] } };
};
Emp.prototype = {
    save: function() {
        alert(JSON.stringify(emps.temp));
        var carrier = [];
        for (var c in emps.temp.created) carrier.push(emps.temp.created[c]);
        for (var u in emps.temp.updated) carrier.push(emps.temp.updated[u]);
        if (emps.temp.removed.length > 0) carrier.push({id:-1, comment:JSON.stringify(emps.temp.removed)});
        var s = JSON.stringify(carrier);
        alert(s);
        $.post("/personnel", {"carrier":s}, function(data) {
            alert(data);
            emps.temp.created = {};
            emps.temp.updated = {};
            emps.temp.removed = [];
            emps.saved = []
            carrier = null;
            req.load("personnel");
        });
    },
    remove: function() {
        var flag = $(".checkedFlag");
         if (flag.length == 0) {
             tool.showHint("Please select an Employee Flag that wants to remove.");
             return false;
         }

        var o = $(".checkedFlag");
        o.addClass("rmFlag");

        var i = o.index();
        if ($(".checkedFlag li[title='id']").text()) {
            var dialog = new Dialog();
            var id = emps.saved[i].id;
            id = parseInt(id);
            if ($.inArray(id, emps.temp.removed) == -1) {
                emps.temp.removed.push(id);
            }
            dialog.change = true;
            dialog.remindSave();
        }
    },
    update: function() {
        var flag = $(".checkedFlag");
         if (flag.length == 0) {
             tool.showHint("Please select an Employee that wants to update.");
             return false;
         }
        this.selpos();
        var i = flag.index();
        var oCached = emps.temp.created[i];
        var isNew = false;
        if ($(".checkedFlag li[title='id']").text()) { // is saved or not
            this.setInput(emps.saved[i]);
            oCached = emps.saved[i];
        } else {
            this.setInput(emps.temp.created[i]);
            isNew = true;
        }

        var dialog = new Dialog("#dialog");
        dialog.show();
        dialog.setButton(1, "Update");
        dialog.btn1Click = function() {
            if (!this.validate()) return false;

            var isUpdated = false;
            var n = $("input#name").val().trim();
            if (n != oCached.name) { oCached.name = n; isUpdated = true; }
            var g = $(":radio[name='gender']:checked").val();
            if (g != oCached.gender) { oCached.gender = g; isUpdated = true; }
            var newPid = $(":radio[name='position']:checked").val();
            var pid = empl.getPosId(oCached.posUri);
            if (pid) {
                if (newPid != pid) { oCached.posUri = newPid; isUpdated = true; }
            }
            var b = $("input#birthday").val();
            if (b != oCached.birthday) { oCached.birthday = b; isUpdated = true; }
            var e = $("input#email").val();
            if (e != oCached.email) { oCached.email = e; isUpdated = true; }
            var p = $("input#phone").val();
            if (p != oCached.phoneNumber) { oCached.phoneNumber = p; isUpdated = true; }

            if (isUpdated && !isNew) {
                emps.temp.updated[i] = oCached;
                this.change = true;
            }
            if (isUpdated) {
                $(".checkedFlag li[title='name']").html("<b>" + oCached.name + "</b>");
                $(".checkedFlag li[title='email']").html(oCached.email);
                $(".checkedFlag li[title='phoneNumber']").html(oCached.phoneNumber);
            }
        };
    },
    add: function() {
        var dialog = new Dialog("#dialog");
        dialog.setButton(1, "Add and Continue");
        dialog.show();
        dialog.btn1Click = function() {
            if (!this.validate()) return false;

            var k = $(".flag").length;
            emps.temp.created[k] = {"name":$("input#name").val(),
                "gender":$(":input:radio[name='gender']:checked").val(),
                "posUri":$(":input:radio[name='position']:checked").val(),
                "birthday":$("input#birthday").val(),
                "email":$("input#email").val(),
                "phoneNumber":$("input#phone").val()
            };
            this.change = true;
            console.log("New Emp: " + JSON.stringify(emps.temp.created[k]));

            var flag = $("<div class='flag'></div>");
            empl.showFlag(k, flag, true);
            tool.reset(this.id);
            console.log("Create a temperary Emp Flag: " + JSON.stringify(emps));
        };
        this.selpos();
    },
    selpos: function() {
        $("#posSelector").empty();
        for (var i in post.saved) {
            var n = post.saved[i].name;
            var id = post.saved[i].id;
            var r = $("<input type='radio' name='position'/>");
            r.attr("value", id);
            r.attr("id", id);
            $("#posSelector").append(r).append("<label for='" + id + "'>" + n + "</label><br>");
        }
    },
    load: function(fn, uri) {
        if (!uri) uri = req.url("personnel");
        $.getJSON(uri, function(data) {
            if (!data) { fn(); return;}
            if (data.personnel.length) emps.saved = data.personnel;
            else emps.saved[0] = data.personnel;
            if (fn) fn();
        });
    },
    list: function() {
            for (var i = 0; i < emps.saved.length; i++) {
                var flag = $("<div class='flag'></div>");
                empl.showFlag(i, flag, false);
            }
    },
    setInput: function(o) {
        $("input#name").val(o.name);
        $("input#birthday").val(o.birthday);
        $("input#email").val(o.email);
        $("input#phone").val(o.phoneNumber);
        $("input#" + o.gender).attr("checked",true);
        var pid = this.getPosId(o.posUri);
        if (pid) {
            $("#posSelector #" + pid).attr("checked", true);
        }
    },
    getPosId: function(posUri) {
        if (!posUri) return 0;
        return posUri.substring(posUri.lastIndexOf("/")+1);
    },
    // todo: following should be extract as a Flag class

    showFlag: function(i, flag, isNew, container, o) {
        if (!o) o = isNew ? emps.temp.created[i] : emps.saved[i];
        if (o.id) {
            $("<li title='id' style='display:none;'>").append(o.id).appendTo(flag);
        }
        $("<li title='name'>").append("<b>" + o.name + "</b>").appendTo(flag);
        if (o.email) $("<li title='email'>").append(o.email).appendTo(flag);
        if (o.phoneNumber) $("<li title='phoneNumber'>").append(o.phoneNumber).appendTo(flag);
        container = !container ? $("#empListDiv") : container;
        container.append(flag);
        this.blink(flag);
        flag.addClass("column");
    },
    blink: function(o) {
        o.hover(function() {
            $(this).addClass("hoverFlag");
        }, function() {
            $(this).removeClass("hoverFlag");
        });
        o.click(function() {
                $(".checkedFlag").removeClass("checkedFlag");
                $(this).addClass("checkedFlag");
                tool.hideHint();
            }
        );
    }
};

//==============================================================================

/**
 * Position operations
 */
var Pos = function() {
    window.post = { saved:[], temp:{ created:{}, updated:{}, removed:[] } };
};
Pos.prototype = {
    save: function() {
        alert(JSON.stringify(post.temp));
        var carrier = [];
        for (var c in post.temp.created) carrier.push(post.temp.created[c]);
        for (var u in post.temp.updated) carrier.push(post.temp.updated[u]);
        if (post.temp.removed.length > 0) carrier.push({id:-1, comment:JSON.stringify(post.temp.removed)});
        var s = JSON.stringify(carrier);
        alert(s);
        $.post("/position", {"carrier":s}, function(data) {
            alert(data);
            post.temp.created = {};
            post.temp.updated = {};
            post.temp.removed = [];
            post.saved = [];
            carrier = null;
            req.load("position");
        });
    },
    remove: function() {
        var flag = $(".checkedFlag");
         if (flag.length == 0) {
             tool.showHint("Please select an Position Flag that wants to remove.");
             $(".v-menuitem").removeClass("clicked");
             return false;
         }

        var o = $(".checkedFlag");
        o.addClass("rmFlag");

        var i = o.index();
        if ($(".checkedFlag li[title='id']").text()) {
            var dialog = new Dialog("#dialog")
            var id = post.saved[i].id;
            id = parseInt(id);
            if ($.inArray(id, post.temp.removed) == -1) {
                post.temp.removed.push(id);
            }
            dialog.change = true;
            dialog.remindSave();
        }
    },
    update: function() {
        var flag = $(".checkedFlag");
         if (flag.length == 0) {
             tool.showHint("Please select an Position that wants to update.");
             $(".v-menuitem").removeClass("clicked");
             return false;
         }
        var i = flag.index();
        var oCached = post.temp.created[i];
        this.selorg();
        var isNew = false;
        if ($(".checkedFlag li[title='id']").text()) { // is saved or not
            this.setInput(post.saved[i]);
            oCached = post.saved[i];
        } else {
            this.setInput(post.temp.created[i]);
            isNew = true;
        }

        var dialog = new Dialog("#dialog");
        dialog.setButton(1, "Update");
        dialog.show();
        dialog.btn1Click = function() {
            if (!this.validate()) return false;

            var isUpdated = false;
            var n = $("input#name").val().trim();
            if (n != oCached.name) { oCached.name = n; isUpdated = true; }
            var g = $(":radio[name='type']:checked").val();
            if (g != oCached.type) { oCached.type = g; isUpdated = true; }
            var newOid = $(":radio[name='organization']:checked").val();
            var oid = tool.getId(oCached.refOrg);
            if (newOid != oid) {
                oCached.refOrg = newOid; isUpdated = true;
            }

            if (isUpdated && !isNew) {
                post.temp.updated[i] = oCached;
                this.change = true;
            }
            if (isUpdated) {
                $(".checkedFlag li[title='name']").html("<b>" + oCached.name + "</b>");
            }
        };
    },
    add: function() {
        var dialog = new Dialog("#dialog");
        dialog.setButton(1, "Add and Continue");
        dialog.btn1Click = function() {
            if (!this.validate()) return false;

            var k = $(".flag").length;
            post.temp.created[k] = {"name":$("input#name").val(),
                "type":$(":input:radio[name='type']:checked").val(),
                "refOrg":$(":input:radio[name='organization']:checked").val()
            };
            this.change = true;
            console.log("New Pos: " + JSON.stringify(post.temp.created[k]));

            var flag = $("<div class='flag'></div>");
            posi.showFlag(k, flag, true);
            tool.reset(this.id);
            console.log("Create a temperary Pos Flag: " + JSON.stringify(post));
        };
        this.selorg();
        $("#orgSelector :radio")[0].checked = true;
        dialog.show();
    },
    selorg: function() {
        $("#orgSelector").empty();
        for (var i in orgs.saved) {
            var n = orgs.saved[i].name;
            var id = orgs.saved[i].id;
            if (id == orgs.root.id) continue;
            var r = $("<input type='radio' name='organization'/>");
            r.attr("value", id);
            r.attr("id", id);
            $("#orgSelector").append(r).append("<label for='" + id + "'>" + n + "</label><br>").show();
        }
    },
    load: function(fn, uri) {
        if (!uri) uri = req.url("position");
        $.getJSON(uri, function(data) {
            if (!data) { fn(); return; }
            if (data.position.length) post.saved = data.position;
            else post.saved[0] = data.position;
            if (fn) fn();
        });
    },
    list: function() {
        for (var i = 0; i < post.saved.length; i++) {
            var flag = $("<div class='flag'></div>");
            posi.showFlag(i, flag, false);
        }
    },
    setInput: function(o) {
        $("input#name").val(o.name);
        $("input#" + o.type).attr("checked","true");
        var oid = tool.getId(o.refOrg);
        if (oid) {
            $("#orgSelector #" + oid).attr("checked", true);
        }
    },

    showFlag: function(i, flag, isNew) {
        var o = isNew ? post.temp.created[i] : post.saved[i];
        if (o.id) {
            $("<li title='id' style='display:none;'>").append(o.id).appendTo(flag);
        }
        $("<li title='name'>").append("<b>" + o.name + "</b>").appendTo(flag);
        $("#posListDiv").append(flag);
        this.blink(flag);
        flag.addClass("column");
    },
    blink: function(o) {
        o.hover(function() {
            $(this).addClass("hoverFlag");
        }, function() {
            $(this).removeClass("hoverFlag");
        });
        o.click(function() {
                $(".checkedFlag").removeClass("checkedFlag");
                $(this).addClass("checkedFlag");
                tool.hideHint();
            }
        );
    }
};

//==============================================================================

/**
 * Dialog
 * @param {String} id  A form id.
 */
var Dialog = function(id) {
    this.id = id;
    this.change = false;
    this.init(this);
};

Dialog.prototype = {

    init: function(d) {
        this.d = $(this.id + "Div");
        this.d.find(":button[name='cancel']").bind("click", function() { d.cancel(); });
        this.d.find(":button:eq(1)").bind("click", function() { d.btn1Click(); });
    },
    show: function() {
        this.cover();
        this.d.show("fast");
    },
    cancel: function() {
        this.d.hide("fast");
        $(".overlay").hide();
        $(".v-menuitem").removeClass("clicked");
        this.remindSave();
        //$(":button:eq(1)").unbind("click"); // if not, click event will repeat.
        tool.reset(this.id);
        this.d.find(":button:eq(1)").unbind("click");
    },
    cover: function() {
        if (!this.overlay) {
            this.overlay = $("<div>").addClass("overlay");
            $("body").append(this.overlay);
        }
        this.overlay.show();
    },
    validate: function() {
        return tool.checkAll(this.id);
    },
    setButton: function(i, n) {
        var b = this.d.find(":button:eq(" + i + ")");
        b.attr("name", n);
        b.attr("value", n);
    },
    remindSave: function(msg) {
        if (!msg) msg = "Please save changes.  &nbsp; <a href='#'>Save Now</a> ";
        if (this.change) {
            if ($(".v-menuitem:eq(0)").css("display") != "none") {
                tool.showHint(msg);
            } else {
                $(".v-menuitem:eq(0)").css("color", "#36c").show();
            }
        }
    }

};

//==============================================================================

/**
 * Tool
 */
var Tool = function() {
    this.urlbase = "http://localhost:8080/";
};

Tool.prototype = {

    /**
     * Hind the bottom hint message.
     */
    hideHint: function() {
        $(".btmHint").animate({height:"0",lineHeight:"0"},"fast").hide("fast");
        $(".btmHint").empty();
    },

    /**
     * Showing the bottom hint message.
     *
     * @param msg A message that is going to show at bottom.
     */
    showHint: function(msg) {
       if($(".btmHint").length == 0) {
           $("<div>").addClass("btmHint").append(msg).appendTo("body");
       } else {
           $(".btmHint").html(msg);
       }
       $(".btmHint").animate({height:"45px",lineHeight:"45px"}, "fast").show();
    },

    checkLength: function (o, min, max) {
        if (o.attr("type") == "submit" || o.attr("type") == "button") return;
        var name = o.attr("name");
        if (!min) min = 6;
        if (!max) max = 30;
        if (name=="password") max=32;

        if (o.val().length > max || o.val().length < min) {
            o.addClass("warn");
            var msg = "<li>Length of " + name + " must be between " +
                    min + " and " + max + "</li>";
            return { "status":false, "msg": msg }
        } else {
            o.removeClass("warn");
            return { "status":true };
        }
    },

    checkEmpty: function(e) {
        if (e.attr("type") == "submit" || e.attr("type") == "button") return;
        if (e.val() == "") {
            e.addClass("warn");
            return "<li>Please enter valid " + e.attr("name") + ".</li>"
        } else {
            e.removeClass("warn");
            return "";
        }

    },

    flash: function(valid, msg, div, cls) {
        var divErr = $("#" + div + " ." + cls);
        if (!valid) {
            if(divErr.is("div")) divErr.html(msg);
            else $("#" + div).prepend($("<div></div>").addClass(cls).html(msg));
            $("#" + div + " ." + cls).fadeIn("fast");
        }
        else { $("#" + div + " ." + cls).fadeOut("fast").remove();}
    },

    /**
     * check one input element
     * @param e An input element jQuery object, something like $("input#email").
     * @param divid An div id, should wrap a form, and the error message will insert after the Div tag.
     */
    checkOne: function(e, divid) {
        var msg = "";
        var emptyInfo = this.checkEmpty(e);
        if (emptyInfo) {
            msg = emptyInfo;
            var divErr = $("#" + divid + " .error");
            if (divErr.is("div")) {
                var li = $(".error li:contains('" + e.attr("name") + "')");
                if (li.length == 0) divErr.append(msg);
            }
            else $("#" + divid).prepend($("<div></div>").addClass("error").html(msg));
        } else {
            $(".error li:contains('" + e.attr("name") + "')").remove();
            if ($(".error li").length == 0) $(".error").remove();
        }
    },

    checkAll: function(f) {
        var msg = "";
        var valid = true;
        var inputs = $(f).find("input");
        for (var i = 0; i < inputs.length; i++) {
            var o = $(inputs[i]);
            if (o.attr("type")=="radio") continue;
              var emptyInfo = this.checkEmpty(o)
              if(emptyInfo) {
                msg += emptyInfo;
                valid = false;
              }
            if (valid) {
                var len = this.checkLength(o);
                if (len && !len.status) {
                    msg += len.msg;
                    valid = false;
                }
            }
        }
        this.flash(valid, "<dd>" + msg + "</dd>", $(f).attr("id") + "Div", "error");

        return valid;
    },

    reset: function(formId) {
        $(":input", formId).not(":button, :submit, :reset, :hidden, :radio")
                .val("").removeAttr("checked").removeAttr("selected");
        $(".error").hide();
        $("input.warn").removeClass("warn");
    },

    getId:function(uri) {
        if (!uri)
            return 0;
        else
            return uri.substring(uri.lastIndexOf("/")+1);
    }

};

//==============================================================================

var Dashboard = function() {};
Dashboard.prototype = {
    h: function(title, content, height) {
        if (!height) height = 200;
        var h = "<h5 class='quiet boxtitle' style='margin-bottom:3px;'>";
        h += title + "</h5>";
        h += "<div style='height:" + height + "px;overflow:auto;'>";
        h += content + "</div>";
        return h;
    },
    loadOverview: function() {
        var div = $("#overview");
        div.empty();
        var ov = orgs.overview;
        if (ov.comment) div.append(this.h("Organization Abstract", ov.comment));
        div.append("<br>");
        if (ov.website) div.append(this.h("Website", ov.website));
        if (ov.country) div.append(this.h("Country", ov.country, 30));
        if (ov.city) div.append(this.h("City", ov.city, 30));
    },
    loadDepts: function() {
        var ul = $("#deptFilterList");
        ul.empty();
        for (var i in orgs.saved) {
            var item = $("<li class='v-menuitem links'>");
            item.attr("id", "dept"+orgs.saved[i].id);
            item.append(orgs.saved[i].name);
            item.appendTo(ul);
        }
        dashboard.link("#deptFilterList .v-menuitem");
        $("#deptHead").text("Department (" + orgs.saved.length + ")");
    },
    loadPosts: function() {
        var ul = $("#posFilterList");
        ul.empty();
        for (var i in post.saved) {
            var item = $("<li class='v-menuitem links'>");
            item.attr("id", "pos"+post.saved[i].id);
            item.append(post.saved[i].name);
            item.appendTo(ul);
        }
        dashboard.link("#posFilterList .v-menuitem");
        $("#posHead").text("Position (" + post.saved.length + ")");
    },
    loadPeople: function(ds) {
        if (ds == null || ds == undefined) ds = emps.saved;

        var div = $("#peopleList");
        div.empty();
        for (var i in ds) {
            empl.showFlag(i, $("<div class='flag'>"), false, div, ds[i]);
        }
        $("#peopleHead").text("People (" + ds.length + ")");
    },
    link: function(selector) {
        $(selector).click(function() {
            $("li.clicked").removeClass("clicked");
            $(this).addClass("clicked");
            var t = $(this).parent()[0].id;
            if (t == "deptFilterList") {
                dashboard.filterPeople("org", this.id.substring(4));
            }
            else if (t == "posFilterList") {
                dashboard.filterPeople("pos", this.id.substring(3));
            }

            return false;
        } );
        $(selector).hover(function() {
            $(this).addClass("overlink"); }, function() {
            $(this).removeClass("overlink");
        });
    },
    filterPeople: function(t, id) {
        var url = req.urlPrefix + "personnel/by@t?id=@id&callback=?";
        url = url.replace("@t", t).replace("@id", id);
        $.getJSON(url, function(data) {
            var ds = [];
            if (data) {
                ds = !data.personnel.length ? $.makeArray(data.personnel) : data.personnel;
            }
            dashboard.loadPeople(ds);
        });
    },
    loadAll: function() {
         orgn.load(dashboard.loadDepts);
         posi.load(dashboard.loadPosts);
         empl.load(dashboard.loadPeople);
    }
};

//==============================================================================

/**
 * assistant for Sign* operations
 */
var Sign = function(fid) {
    this.signinFid = "form#signin";
    this.signupFid = "form#signup";
    this.init(this);
};
Sign.prototype = {
    init: function(o) {
        $("a#signin").click(function() { $("#content").load("/signin"); });
        $("a#signup").click(function() { $("#content").load("/signup",
            function() {
                $("a#signin").show();
                $("a#signup, a#signout").hide();
                $(":button[name='signup']").bind("click", function() {
                    sign.signup();
                });
            });
        });
        $("a#signout").click(function() { sign.signout(); });
        if (getCookie("email")) {
         $("#content").load("/dashboard", function() {
             sign.setModuleButtons();
             $(".imgbtn img[title='Dashboard']").addClass("clicked");
             dashboard.loadAll();
         });
        } else {
         $("#content").load("/signin", function() {
             $(":button[name='signin']").bind("click", function() {sign.signin();});
             $("a#signup").show();
             $("a#signin, #signout").hide();
         });
        }
    },
    signout: function() {
         $("#content").load("/signout", function(){
             $("#signin").show(); $("a#signup, a#signout").hide();
             $("div.imgbtn").hide();
             $(":button[name='signin']").bind("click", function() {sign.signin();});
         });
    },
    signin: function() {
        if (!tool.checkAll(sign.signinFid)) return false;
        sign.form = $(sign.signinFid);
        var em = sign.form[0].email.value;
        var psw = sign.form[0].password.value;
        var data = {email:em, password:psw};
        $.post("/signin", data, function(rt) {
            $("#content").html(rt);
            $(":button[name='signin']").bind("click", function() {sign.signin();});
            sign.setModuleButtons();
            $(".imgbtn img[title='Dashboard']").addClass("clicked");
            dashboard.loadAll();
        }).error(function(a) { alert(a); });
    },
    signup: function() {
        if (!tool.checkAll(sign.signupFid)) return false;
        var form = $(sign.signupFid);
        var ws = form[0].website.value;
        var nm = form[0].name.value;
        var em = form[0].email.value;
        var psw = form[0].password.value;
        var data = {website: ws, name:nm, email:em, password:psw};
        $.post("/signup", data, function(rt) {
            $("#content").html(rt);
            $(":button[name='signup']").bind("click", function() {sign.signup();});
        });
    },
    setModuleButtons: function() {
        if (getCookie("email")) {
            $("a#signout").show();
            $("a#signin,a#signup").hide();
            $("#header .logo").after("<div class='span-1 imgbtn'><img title='Dashboard' src='../images/dashboard.gif'/></div><div class='span-1 imgbtn'><img title='Personnel' src='../images/employee.gif'/></div><div class='span-1 imgbtn'><img title='Position' src='../images/position.gif'/></div><div class='span-1 imgbtn'><img title='Organization' src='../images/organization.gif'/></div>");
            $(".imgbtn img").hover(function(){$(this).addClass("over");},function(){$(this).removeClass("over");});
            $(".imgbtn img").bind("mousedown", function() {$("img.clicked").removeClass("clicked");$(this).addClass("clicked");});
            $(".imgbtn img").bind("click", function() {
                var m = $(this).attr("title");
                if (window.checkedModule != m) {
                    window.checkedModule = m;
                    req.load(m.toLowerCase());
                }
            });
        }
    }
};

//==============================================================================

/**
 * Menuitem for right side control.
 */
var Menuitem = function() {
};

Menuitem.prototype = {

    click: function(menuId) {
        $(".v-menuitem").removeClass("clicked");
        $("#" + menuId).addClass("clicked");

        switch(menuId) {
            case "createOrg":
                orgn.add();
                break;
            case "updateOrg":
                orgn.update();
                break;
            case "saveOrg":
                orgn.save();
                break;
            case "deleteOrg":
                orgn.remove();
                break;

            case "addEmp":
                empl.add();
                break;
            case "updateEmp":
                empl.update();
                break;
            case "removeEmp":
                empl.remove();
                break;
            case "saveEmp":
                empl.save();
                break;

            case "addPos":
                posi.add();
                break;
            case "updatePos":
                posi.update();
                break;
            case "removePos":
                posi.remove();
                break;
            case "savePos":
                posi.save();
                break;
            default:
        }
    }
};

//==============================================================================

function getCookieObj(k) {
    var jsonStr = getCookie(k)
    var o = parseObj(jsonStr);
    if (typeof(o) == "string") o = parseObj(o);
    return o;
}

function setCookie(name, v, exdays) {
    var exdate = new Date();
    exdate.setDate(exdate.getDate() + exdays);
    var value = v + ((exdays == null) ? "" : "; expires=" + exdate.toUTCString());
    document.cookie = name + "=" + value;
}


function getCookie(k) {
    var cookies = document.cookie.split(";");
    for (var i in cookies) {
        var _k = cookies[i].substr(0,cookies[i].indexOf("="));
        var _v = cookies[i].substr(cookies[i].indexOf("=")+1);
        if (_k == k) return _v;
        else return "";
    }
}

function parseObj(strData) {
    return (new Function("return " + strData))();
}


$(function(){
    window.sign = new Sign();
    window.tool = new Tool();
    window.menu = new Menuitem();
    window.req = new Request();
    window.orgn = new Org();
    window.posi = new Pos();
    window.empl = new Emp();
    window.dashboard = new Dashboard();
});
